package com.ayf.payment.game.api.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.ayf.payment.game.api.channel.alipay.service.AliPayService;
import com.ayf.payment.game.api.dto.alipay.AliOrderResult;
import com.ayf.payment.game.api.dto.alipay.AliOrderStatus;
import com.ayf.payment.game.api.dto.alipay.MerchantAlipayOrderDTO;
import com.ayf.payment.game.api.dto.criteria.MerchantAlipayOrderCriteria;
import com.ayf.payment.game.api.entity.MerchantAliBatchPayFile;
import com.ayf.payment.game.api.entity.MerchantAliBatchPayFileFailReason;
import com.ayf.payment.game.api.entity.MerchantAlipayOrder;
import com.ayf.payment.game.api.mapper.MerchantAliBatchPayFileFailReasonMapper;
import com.ayf.payment.game.api.mapper.MerchantAlipayOrderMapper;
import com.ayf.payment.game.api.service.MerchantAliBatchPayFileService;
import com.ayf.payment.game.api.service.MerchantAlipayOrderService;
import com.ayf.payment.game.api.utils.DateUtils;
import com.ayf.payment.game.api.utils.SnowFlakeUtils;
import com.swwx.charm.commons.lang.utils.BeanConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MerchantAlipayOrderServiceImpl implements MerchantAlipayOrderService {

    @Resource
    private MerchantAlipayOrderMapper merchantAlipayOrderMapper;
    @Resource
    private MerchantAliBatchPayFileFailReasonMapper merchantAliBatchPayFileFailReasonMapper;
    @Autowired
    private MerchantAliBatchPayFileService merchantAliBatchPayFileService;
    @Autowired
    private AliPayService aliPayService;

    @Override
    public boolean updateOrderStatus(AliOrderResult aliOrderResult) {
        return merchantAlipayOrderMapper.updateOrderStatus(aliOrderResult) > 0;
    }

    @Override
    public void save(MerchantAlipayOrderDTO dto) {
        Date date = new Date();
        dto.setCreateTime(date);
        dto.setCreateDateIndex(DateUtils.dateToInteger(date));
        dto.setStatus(AliOrderStatus.PROCESSING.getCode());
        dto.setPayType(1);
        dto.setBathNo(dto.getMerchantOrderNo());
        MerchantAlipayOrder alipayOrder = BeanConvertUtils.convert(dto, MerchantAlipayOrder.class);
        merchantAlipayOrderMapper.insertSelective(alipayOrder);
    }

    @Override
    public MerchantAlipayOrder getRealTimePayOrder(String mMerchantOrderNo) {
        MerchantAlipayOrder merchantAlipayOrder = new MerchantAlipayOrder();
        merchantAlipayOrder.setMerchantOrderNo(mMerchantOrderNo);
        return merchantAlipayOrderMapper.selectOne(merchantAlipayOrder);
    }

    @Override
    public boolean addAliPayOrder(MerchantAlipayOrderDTO dto) {
        Date date = new Date();
        dto.setCreateTime(date);
        dto.setCreateDateIndex(DateUtils.dateToInteger(date));
        dto.setStatus(AliOrderStatus.PROCESSING.getCode());
        dto.setPayType(1);
        dto.setMerchantOrderNo("ZD".concat(DateUtils.dateToString(DateUtils.getNowDate(), "yyMMdd").concat(SnowFlakeUtils.getUniqueId())));
        dto.setBathNo("ZC".concat(DateUtils.dateToString(DateUtils.getNowDate(), "yyMMdd").concat(SnowFlakeUtils.getUniqueId())));
        MerchantAlipayOrder alipayOrder = BeanConvertUtils.convert(dto, MerchantAlipayOrder.class);
        merchantAlipayOrderMapper.insertSelective(alipayOrder);
        String traceId = SnowFlakeUtils.getTraceId();
        dto.setTraceId(traceId);

        Map<String, Object> map = aliPayService.balanceQuery(traceId, dto.getMerchantId(), dto.getMerchantOrderNo());
        BigDecimal balance = (BigDecimal) map.get("balance");
        if ("1".equals(map.get("status").toString())) {
            if (dto.getTransAmount().compareTo(balance) > 0) {
                AliOrderResult aliOrderResult = new AliOrderResult();
                aliOrderResult.setMerchantOrderNo(dto.getMerchantOrderNo());
                aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
                aliOrderResult.setApplyTime(new Date());
                aliOrderResult.setAppId(String.valueOf(map.get("appId")));
                aliOrderResult.setFailReason("支付宝账号余额不足，余额为：" + balance + "元");
                updateOrderStatus(aliOrderResult);
            } else {
                //弃用
                aliPayService.orderCreate(dto);
            }
        } else {
            AliOrderResult aliOrderResult = new AliOrderResult();
            aliOrderResult.setMerchantOrderNo(dto.getMerchantOrderNo());
            aliOrderResult.setStatus(AliOrderStatus.FAIL.getCode());
            aliOrderResult.setApplyTime(new Date());
            aliOrderResult.setAppId(String.valueOf(map.get("appId")));
            aliOrderResult.setFailReason(String.valueOf(map.get("msg")));
            updateOrderStatus(aliOrderResult);
        }
        return true;
    }

    @Override
    public boolean bathAddAliPayOrder(List<MerchantAlipayOrder> list, List<MerchantAliBatchPayFileFailReason> failList, MerchantAliBatchPayFile batchPayFile) {
        merchantAliBatchPayFileService.addPayFile(batchPayFile);
        int batchSize = 200;
        if (CollUtil.isNotEmpty(failList)) {
            int num = failList.size() % batchSize == 0 ? failList.size() / batchSize : failList.size() / batchSize + 1;
            for (int i = 0; i < num; i++) {
                List<MerchantAliBatchPayFileFailReason> subList = failList.subList(i * batchSize, i == num - 1 ? failList.size() :
                        (i + 1) * batchSize);
                merchantAliBatchPayFileFailReasonMapper.batchAddFailReason(subList);
            }
        } else if (CollUtil.isNotEmpty(list)) {
            int num = list.size() % batchSize == 0 ? list.size() / batchSize : list.size() / batchSize + 1;
            for (int i = 0; i < num; i++) {
                List<MerchantAlipayOrder> subList = list.subList(i * batchSize, i == num - 1 ? list.size() :
                        (i + 1) * batchSize);
                merchantAlipayOrderMapper.bathAddAliPayOrder(subList);
            }
        }
        return true;
    }

    @Override
    public List<MerchantAlipayOrderDTO> list(MerchantAlipayOrderCriteria criteria) {
        return merchantAlipayOrderMapper.list(criteria);
    }
}

